home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / terms / tip / tip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-10  |  12.9 KB  |  671 lines

  1. /*
  2.  * Copyright (c) 1983 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. char copyright[] =
  20. "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
  21.  All rights reserved.\n";
  22. #endif /* not lint */
  23.  
  24. #ifndef lint
  25. static char sccsid[] = "@(#)tip.c    5.8 (Berkeley) 9/2/88";
  26. #endif /* not lint */
  27.  
  28. /*
  29.  * tip - UNIX link to other systems
  30.  *  tip [-psv] [-speed] system-name [data]
  31.  * or
  32.  *  cu phone-number [-s speed] [-l line] [-a acu]
  33.  */
  34. #include "tip.h"
  35.  
  36. /*
  37.  * Baud rate mapping table
  38.  */
  39. int bauds[] = {
  40.     0, 50, 75, 110, 134, 150, 200, 300, 600,
  41.     1200, 1800, 2400, 4800, 9600, 19200, 38400, -1
  42. };
  43.  
  44. int    page;
  45. int    disc = OTTYDISC;        /* tip normally runs this way */
  46. sigfunc_t    intprompt();
  47. sigfunc_t    timeout();
  48. sigfunc_t    cleanup();
  49. char    *login();
  50. char    *sname();
  51. char    PNbuf[256];            /* This limits the size of a number */
  52.  
  53. main(argc, argv)
  54.     char *argv[];
  55. {
  56.     int uuid;
  57.     char *system = NOSTR;
  58.     char *data = NOSTR;
  59.     register int i;
  60.     register char *p;
  61.     char sbuf[12];
  62.  
  63.     uid = getuid();
  64.     gid = getgid();
  65.     euid = geteuid();    /* should be root */
  66.     egid = getegid();
  67.     uuid = getuucpuid();
  68.     
  69.     if (equal(sname(argv[0]), "cu")) {
  70.         setreuid(uid, uuid);
  71.         cumode = 1;
  72.         cumain(argc, argv);
  73.         goto cucommon;
  74.     }
  75.  
  76.     if (argc < 2) {
  77.         fprintf(stderr, "usage: tip [-psv] [-speed] [system-name] [data]\n");
  78.         exit(1);
  79.     }
  80.  
  81.     for (; argc > 1; argv++, argc--) {
  82.         if (argv[1][0] != '-') {
  83.             if (system)
  84.                 data = argv[1];
  85.             else
  86.                 system = argv[1];
  87.         }
  88.         else switch (argv[1][1]) {
  89.  
  90.         case 'p':
  91.             page++;
  92.             break;
  93.         case 's':
  94.             slip++;
  95.             break;
  96.         case 'v':
  97.             vflag++;
  98.             break;
  99.  
  100.         case '0': case '1': case '2': case '3': case '4':
  101.         case '5': case '6': case '7': case '8': case '9':
  102.             BR = atoi(&argv[1][1]);
  103.             break;
  104.  
  105.         default:
  106.             fprintf(stderr, "tip: %s, unknown option\n", argv[1]);
  107.             break;
  108.         }
  109.     }
  110.     if (!isatty(0) && !slip && !page) {
  111.         fprintf(stderr, "tip: warning: input is not a tty\n");
  112.     }
  113.     if (slip) {
  114.         setreuid(euid, uuid);
  115.         uid = 0;
  116.     } else {
  117.         setreuid(uid, uuid);
  118.     }
  119.     euid = uuid;
  120.  
  121.     if (system == NOSTR)
  122.         goto notnumber;
  123.     if (isalpha(*system))
  124.         goto notnumber;
  125.     /*
  126.      * System name is really a phone number...
  127.      * Copy the number then stomp on the original (in case the number
  128.      *    is private, we don't want 'ps' or 'w' to find it).
  129.      */
  130.     if (strlen(system) > sizeof PNbuf - 1) {
  131.         fprintf(stderr, "tip: phone number too long (max = %d bytes)\n",
  132.             sizeof PNbuf - 1);
  133.         exit(1);
  134.     }
  135.     strncpy( PNbuf, system, sizeof PNbuf - 1 );
  136.     for (p = system; *p; p++)
  137.         *p = '\0';
  138.     PN = PNbuf;
  139.     (void)sprintf(sbuf, "tip%d", BR);
  140.     system = sbuf;
  141.  
  142. notnumber:
  143.     signal(SIGINT, cleanup);
  144.     signal(SIGQUIT, cleanup);
  145.     signal(SIGHUP, cleanup);
  146.     signal(SIGTERM, cleanup);
  147.     signal(SIGPIPE, cleanup);
  148.  
  149.     if ((i = hunt(system)) == 0) {
  150.         printf("all ports busy\n");
  151.         exit(3);
  152.     }
  153.     if (i == -1) {
  154.         printf("link down\n");
  155.         (void)uu_unlock(uucplock);
  156.         exit(3);
  157.     }
  158.     setbuf(stdout, NULL);
  159.     loginit();
  160.  
  161.     /*
  162.      * Kludge, their's no easy way to get the initialization
  163.      *   in the right order, so force it here
  164.      */
  165.     if ((PH = getenv("PHONES")) == NOSTR)
  166.         PH = "/etc/phones";
  167.     vinit();                /* init variables */
  168.     setparity("none");            /* set the parity table */
  169.     if ((i = speed(number(value(BAUDRATE)))) == NULL) {
  170.         printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
  171.         (void)uu_unlock(uucplock);
  172.         exit(3);
  173.     }
  174.  
  175.     if (slip) {
  176.         if (SA == NOSTR) {
  177.             printf("tip: local addr not set\n");
  178.             uu_unlock(uucplock);
  179.             exit(3);
  180.         }
  181.         if (DA == NOSTR) {
  182.             printf("tip: destination addr not set\n");
  183.             uu_unlock(uucplock);
  184.             exit(3);
  185.         }
  186.         if (SM == NOSTR) {
  187.             printf("tip: slip netmask not set\n");
  188.             uu_unlock(uucplock);
  189.             exit(3);
  190.         }
  191.     }
  192.  
  193.     /*
  194.      * Now that we have the logfile and the ACU open
  195.      *  return to the real uid and gid.  These things will
  196.      *  be closed on exit.  Swap real and effective uid's
  197.      *  so we can get the original permissions back
  198.      *  for removing the uucp lock.
  199.      */
  200.     user_uid();    /* in the case of slip, we are now priviliged */
  201.  
  202.     /*
  203.      * Hardwired connections require the
  204.      *  line speed set before they make any transmissions
  205.      *  (this is particularly true of things like a DF03-AC)
  206.      */
  207.     if (HW)
  208.         ttysetup(i);
  209.     if (p = lconnect()) {
  210.         printf("\07%s\n[EOT]\n", p);
  211.         daemon_uid();
  212.         (void)uu_unlock(uucplock);
  213.         exit(1);
  214.     }
  215.     if (!HW)
  216.         ttysetup(i);
  217.  
  218.  
  219.     if (LS != NOSTR) {
  220.         fprintf(stderr, "\07[Logging in...]\r\n");
  221.         if (p = login()) {
  222.             printf("\07%s\n[EOT]\n", p);
  223.             daemon_uid();
  224.             (void)uu_unlock(uucplock);
  225.             exit(1);
  226.         }
  227.     }
  228.  
  229.     if (page) {
  230.         i = sendpage(data);
  231.         daemon_uid();
  232.         (void)uu_unlock(uucplock);
  233.         exit(i);
  234.     }
  235.  
  236.     if (slip) {
  237.         i = runslip();
  238.         daemon_uid();
  239.         (void)uu_unlock(uucplock);
  240.         exit(i);
  241.     }
  242.  
  243. cucommon:
  244.     /*
  245.      * From here down the code is shared with
  246.      * the "cu" version of tip.
  247.      */
  248.  
  249.     ioctl(0, TIOCGETP, (char *)&defarg);
  250.     ioctl(0, TIOCGETC, (char *)&defchars);
  251.     ioctl(0, TIOCGLTC, (char *)&deflchars);
  252.     ioctl(0, TIOCGETD, (char *)&odisc);
  253.     arg = defarg;
  254.     arg.sg_flags = ANYP | CBREAK;
  255.     tchars = defchars;
  256.     tchars.t_intrc = tchars.t_quitc = -1;
  257.     ltchars = deflchars;
  258.     ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc
  259.         = ltchars.t_lnextc = -1;
  260.     raw();
  261.  
  262.     pipe(fildes); pipe(repdes);
  263.     signal(SIGALRM, timeout);
  264.  
  265.     /*
  266.      * Everything's set up now:
  267.      *    connection established (hardwired or dialup)
  268.      *    line conditioned (baud rate, mode, etc.)
  269.      *    internal data structures (variables)
  270.      * so, fork one process for local side and one for remote.
  271.      */
  272.     printf(cumode ? "Connected\r\n" : "\07connected\r\n");
  273.     if (pid = fork())
  274.         tipin();
  275.     else
  276.         tipout();
  277.     /*NOTREACHED*/
  278. }
  279.  
  280. sigfunc_t
  281. cleanup()
  282. {
  283.  
  284.     daemon_uid();
  285.     (void)uu_unlock(uucplock);
  286.     if (pid) {
  287.         (void) kill(pid, SIGTERM);
  288.         unraw();
  289.     } else if (odisc)
  290.         ioctl(0, TIOCSETD, (char *)&odisc);
  291.     exit(0);
  292. }
  293.  
  294. /*
  295.  * Muck with user ID's.  We are setuid to the owner of the lock
  296.  * directory when we start.  user_uid() reverses real and effective
  297.  * ID's after startup, to run with the user's permissions.
  298.  * daemon_uid() switches back to the privileged uid for unlocking.
  299.  * Finally, to avoid running a shell with the wrong real uid,
  300.  * shell_uid() sets real and effective uid's to the user's real ID.
  301.  */
  302. static int uidswapped;
  303.  
  304. user_uid()
  305. {
  306.     if (uidswapped == 0) {
  307.         setregid(egid, gid);
  308.         setreuid(euid, uid);
  309.         uidswapped = 1;
  310.     }
  311. }
  312.  
  313. daemon_uid()
  314. {
  315.     if (uidswapped) {
  316.         setreuid(uid, euid);
  317.         setregid(gid, egid);
  318.         uidswapped = 0;
  319.     }
  320. }
  321.  
  322. shell_uid()
  323. {
  324.  
  325.     setreuid(uid, uid);
  326.     setregid(gid, gid);
  327. }
  328.  
  329. /*
  330.  * put the controlling keyboard into raw mode
  331.  */
  332. raw()
  333. {
  334.  
  335.     ioctl(0, TIOCSETP, &arg);
  336.     ioctl(0, TIOCSETC, &tchars);
  337.     ioctl(0, TIOCSLTC, <chars);
  338.     ioctl(0, TIOCSETD, (char *)&disc);
  339. }
  340.  
  341.  
  342. /*
  343.  * return keyboard to normal mode
  344.  */
  345. unraw()
  346. {
  347.  
  348.     ioctl(0, TIOCSETD, (char *)&odisc);
  349.     ioctl(0, TIOCSETP, (char *)&defarg);
  350.     ioctl(0, TIOCSETC, (char *)&defchars);
  351.     ioctl(0, TIOCSLTC, (char *)&deflchars);
  352. }
  353.  
  354. static    jmp_buf promptbuf;
  355.  
  356. /*
  357.  * Print string ``s'', then read a string
  358.  *  in from the terminal.  Handles signals & allows use of
  359.  *  normal erase and kill characters.
  360.  */
  361. prompt(s, p)
  362.     char *s;
  363.     register char *p;
  364. {
  365.     register char *b = p;
  366.     sigfunc_t (*oint)(), (*oquit)();
  367.  
  368.     stoprompt = 0;
  369.     oint = signal(SIGINT, intprompt);
  370.     oquit = signal(SIGQUIT, SIG_IGN);
  371.     unraw();
  372.     printf("%s", s);
  373.     if (setjmp(promptbuf) == 0)
  374.         while ((*p = getchar()) != EOF && *p != '\n')
  375.             p++;
  376.     *p = '\0';
  377.  
  378.     raw();
  379.     signal(SIGINT, oint);
  380.     signal(SIGQUIT, oint);
  381.     return (stoprompt || p == b);
  382. }
  383.  
  384. /*
  385.  * Interrupt service routine during prompting
  386.  */
  387. sigfunc_t
  388. intprompt()
  389. {
  390.  
  391.     signal(SIGINT, SIG_IGN);
  392.     stoprompt = 1;
  393.     printf("\r\n");
  394.     longjmp(promptbuf, 1);
  395. }
  396.  
  397. /*
  398.  * ****TIPIN   TIPIN****
  399.  */
  400. tipin()
  401. {
  402.     char gch, bol = 1;
  403.  
  404.     /*
  405.      * Kinda klugey here...
  406.      *   check for scripting being turned on from the .tiprc file,
  407.      *   but be careful about just using setscript(), as we may
  408.      *   send a SIGEMT before tipout has a chance to set up catching
  409.      *   it; so wait a second, then setscript()
  410.      */
  411.     if (boolean(value(SCRIPT))) {
  412.         sleep(1);
  413.         setscript();
  414.     }
  415.  
  416.     while (1) {
  417.         gch = getchar()&0177;
  418.         if ((gch == character(value(ESCAPE))) && bol) {
  419.             if (!(gch = escape()))
  420.                 continue;
  421.         } else if (!cumode && gch == character(value(RAISECHAR))) {
  422.             boolean(value(RAISE)) = !boolean(value(RAISE));
  423.             continue;
  424.         } else if (gch == '\r') {
  425.             bol = 1;
  426.             pwrite(FD, &gch, 1);
  427.             if (boolean(value(HALFDUPLEX)))
  428.                 printf("\r\n");
  429.             continue;
  430.         } else if (!cumode && gch == character(value(FORCE)))
  431.             gch = getchar()&0177;
  432.         bol = any(gch, value(EOL));
  433.         if (boolean(value(RAISE)) && islower(gch))
  434.             gch = toupper(gch);
  435.         pwrite(FD, &gch, 1);
  436.         if (boolean(value(HALFDUPLEX)))
  437.             printf("%c", gch);
  438.     }
  439. }
  440.  
  441. /*
  442.  * Escape handler --
  443.  *  called on recognition of ``escapec'' at the beginning of a line
  444.  */
  445. escape()
  446. {
  447.     register char gch;
  448.     register esctable_t *p;
  449.     char c = character(value(ESCAPE));
  450.     extern esctable_t etable[];
  451.  
  452.     gch = (getchar()&0177);
  453.     for (p = etable; p->e_char; p++)
  454.         if (p->e_char == gch) {
  455.             if ((p->e_flags&PRIV) && uid)
  456.                 continue;
  457.             printf("%s", ctrl(c));
  458.             (*p->e_func)(gch);
  459.             return (0);
  460.         }
  461.     /* ESCAPE ESCAPE forces ESCAPE */
  462.     if (c != gch)
  463.         pwrite(FD, &c, 1);
  464.     return (gch);
  465. }
  466.  
  467. speed(n)
  468.     int n;
  469. {
  470.     register int *p;
  471.  
  472.     for (p = bauds; *p != -1;  p++)
  473.         if (*p == n)
  474.             return (p - bauds);
  475.     return (NULL);
  476. }
  477.  
  478. any(c, p)
  479.     register char c, *p;
  480. {
  481.     while (p && *p)
  482.         if (*p++ == c)
  483.             return (1);
  484.     return (0);
  485. }
  486.  
  487. size(s)
  488.     register char    *s;
  489. {
  490.     register int i = 0;
  491.  
  492.     while (s && *s++)
  493.         i++;
  494.     return (i);
  495. }
  496.  
  497. char *
  498. interp(s)
  499.     register char *s;
  500. {
  501.     static char buf[256];
  502.     register char *p = buf, c, *q;
  503.  
  504.     while (c = *s++) {
  505.         for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
  506.             if (*q++ == c) {
  507.                 *p++ = '\\'; *p++ = *q;
  508.                 goto next;
  509.             }
  510.         if (c < 040) {
  511.             *p++ = '^'; *p++ = c + 'A'-1;
  512.         } else if (c == 0177) {
  513.             *p++ = '^'; *p++ = '?';
  514.         } else
  515.             *p++ = c;
  516.     next:
  517.         ;
  518.     }
  519.     *p = '\0';
  520.     return (buf);
  521. }
  522.  
  523. char *
  524. ctrl(c)
  525.     char c;
  526. {
  527.     static char s[3];
  528.  
  529.     if (c < 040 || c == 0177) {
  530.         s[0] = '^';
  531.         s[1] = c == 0177 ? '?' : c+'A'-1;
  532.         s[2] = '\0';
  533.     } else {
  534.         s[0] = c;
  535.         s[1] = '\0';
  536.     }
  537.     return (s);
  538. }
  539.  
  540. /*
  541.  * Help command
  542.  */
  543. help(c)
  544.     char c;
  545. {
  546.     register esctable_t *p;
  547.     extern esctable_t etable[];
  548.  
  549.     printf("%c\r\n", c);
  550.     for (p = etable; p->e_char; p++) {
  551.         if ((p->e_flags&PRIV) && uid)
  552.             continue;
  553.         printf("%2s", ctrl(character(value(ESCAPE))));
  554.         printf("%-2s %c   %s\r\n", ctrl(p->e_char),
  555.             p->e_flags&EXP ? '*': ' ', p->e_help);
  556.     }
  557. }
  558.  
  559. /*
  560.  * Set up the "remote" tty's state
  561.  */
  562. ttysetup(speed)
  563.     int speed;
  564. {
  565.     unsigned bits = LDECCTQ;
  566.  
  567.     arg.sg_ispeed = arg.sg_ospeed = speed;
  568.     arg.sg_flags = RAW;
  569.     if (boolean(value(TAND)))
  570.         arg.sg_flags |= TANDEM;
  571.     if (boolean(value(DTRHUP))) {
  572.         ioctl(FD, TIOCSDTR, 0);
  573.         ioctl(FD, TIOCHPCL, 0);
  574.     }
  575.     ioctl(FD, TIOCSETP, (char *)&arg);
  576.     ioctl(FD, TIOCLBIS, (char *)&bits);
  577. }
  578.  
  579. /*
  580.  * Return "simple" name from a file name,
  581.  * strip leading directories.
  582.  */
  583. char *
  584. sname(s)
  585.     register char *s;
  586. {
  587.     register char *p = s;
  588.  
  589.     while (*s)
  590.         if (*s++ == '/')
  591.             p = s;
  592.     return (p);
  593. }
  594.  
  595. static char partab[0200];
  596.  
  597. /*
  598.  * Do a write to the remote machine with the correct parity.
  599.  * We are doing 8 bit wide output, so we just generate a character
  600.  * with the right parity and output it.
  601.  */
  602. pwrite(fd, buf, n)
  603.     int fd;
  604.     char *buf;
  605.     register int n;
  606. {
  607.     register int i;
  608.     register char *bp;
  609.     extern int errno;
  610.  
  611.     bp = buf;
  612.     for (i = 0; i < n; i++) {
  613.         *bp = partab[(*bp) & 0177];
  614.         bp++;
  615.     }
  616.     if (write(fd, buf, n) < 0) {
  617.         if (errno == EIO)
  618.             abort("Lost carrier.");
  619.         /* this is questionable */
  620.         perror("write");
  621.     }
  622. }
  623.  
  624. /*
  625.  * Build a parity table with appropriate high-order bit.
  626.  */
  627. setparity(defparity)
  628.     char *defparity;
  629. {
  630.     register int i;
  631.     char *parity;
  632.     extern char evenpartab[];
  633.  
  634.     if (value(PARITY) == NOSTR)
  635.         value(PARITY) = defparity;
  636.     parity = value(PARITY);
  637.     for (i = 0; i < 0200; i++)
  638.         partab[i] = evenpartab[i];
  639.     if (equal(parity, "even"))
  640.         return;
  641.     if (equal(parity, "odd")) {
  642.         for (i = 0; i < 0200; i++)
  643.             partab[i] ^= 0200;    /* reverse bit 7 */
  644.         return;
  645.     }
  646.     if (equal(parity, "none") || equal(parity, "zero")) {
  647.         for (i = 0; i < 0200; i++)
  648.             partab[i] &= ~0200;    /* turn off bit 7 */
  649.         return;
  650.     }
  651.     if (equal(parity, "one")) {
  652.         for (i = 0; i < 0200; i++)
  653.             partab[i] |= 0200;    /* turn on bit 7 */
  654.         return;
  655.     }
  656.     fprintf(stderr, "%s: unknown parity value\n", PA);
  657.     fflush(stderr);
  658. }
  659.  
  660. /* The uid could be determined by stat()-ing ACULOG */
  661. getuucpuid()
  662. {
  663.     struct passwd *pw;
  664.  
  665.     if ((pw = getpwnam("uucp")) == NULL) {
  666.         fprintf(stderr, "tip: unable to get uucp uid\n");
  667.         exit(1);
  668.     }
  669.     return(pw->pw_uid);
  670. }
  671.